package com.ruoyi.reportTask.job;

import com.ruoyi.reportTask.domain.IndustrialReportTask;
import com.ruoyi.reportTask.domain.IndustrialReportTaskCenter;
import com.ruoyi.reportTask.mapper.IndustrialReportTaskMapper;
import com.ruoyi.reportTask.mapper.IndustrialReportTaskCenterMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.xxl.job.core.handler.annotation.XxlJob;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 填报任务生成器定时任务
 * 根据 IndustrialReportTask 表生成 IndustrialReportTaskCenter 任务
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ReportTaskGeneratorJob {

    @Value("${hbyd.industrial.report-url}")
    private String reportUrl;

    private final IndustrialReportTaskMapper taskMapper;
    private final IndustrialReportTaskCenterMapper centerMapper;

    private final SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    private final SimpleDateFormat dateFormatCh = new SimpleDateFormat("yyyy年MM月dd日");

    @XxlJob("generateReportTaskJob")
    public void generateTasks() {
        log.info("定时任务开始执行");

        List<IndustrialReportTask> tasks = taskMapper.selectList(null);
        if (tasks == null || tasks.isEmpty()) {
            log.warn("未查询到任何任务，跳过执行");
            return;
        }

        Date now = new Date();

        for (IndustrialReportTask task : tasks) {
            try {
                if (!isTaskActive(task)) {
                    continue;
                }

                Date taskTime = getTaskTriggerTime(task, now);
                if (taskTime == null) {
                    continue;
                }

                if (centerMapper.existsTaskForDate(task.getId(), taskTime)) {
                    log.info("任务 {} 当天已生成，跳过", task.getTaskName());
                    continue;
                }

                // 创建中心任务
                IndustrialReportTaskCenter centerTask = buildCenterTask(task, now, taskTime);
                centerMapper.insert(centerTask);

                log.info("生成任务成功: {} | reportCollectDate={} | deadline={}",
                    centerTask.getTaskName(),
                    dateFormat.format(centerTask.getReportCollectDate()),
                    dateTimeFormat.format(centerTask.getDeadline()));

            } catch (Exception e) {
                log.error("生成任务异常: {}", task.getTaskName(), e);
            }
        }

        log.info("定时任务执行完成");
    }

    // -------------------------------------------------------------------
    // 判断任务是否有效
    // -------------------------------------------------------------------
    private boolean isTaskActive(IndustrialReportTask task) {
        if (task == null) {
            return false;
        }
        if (!"0".equals(task.getDelFlag()) && !"0L".equals(task.getDelFlag())) {
            return false;
        }
        return task.getDataStatus() != null && task.getDataStatus() == 3;
    }

    // -------------------------------------------------------------------
    // 计算任务触发时间
    // -------------------------------------------------------------------
    private Date getTaskTriggerTime(IndustrialReportTask task, Date now) throws Exception {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);

        switch (task.getReportCycle()) {

            case "1": // 一次性
                if (task.getSendDate() != null && task.getSendDate().before(now)) {
                    return task.getSendDate();
                }
                break;

            case "2": // 月度
                if (task.getSendDay() == null) return null;
                if (calendar.get(Calendar.DAY_OF_MONTH) == task.getSendDay()) {
                    return buildDateWithTime(now, task.getSendTime());
                }
                break;

            case "3": // 年度
                if (task.getSendMonth() == null || task.getSendDay() == null) return null;
                int month = calendar.get(Calendar.MONTH) + 1;
                int day = calendar.get(Calendar.DAY_OF_MONTH);
                if (month == task.getSendMonth() && day == task.getSendDay()) {
                    return buildDateWithTime(now, task.getSendTime());
                }
                break;

            default:
                log.warn("无法识别的任务周期：{}", task.getReportCycle());
        }

        return null;
    }

    // -------------------------------------------------------------------
    // 构建中心任务对象
    // -------------------------------------------------------------------
    private IndustrialReportTaskCenter buildCenterTask(IndustrialReportTask task, Date now, Date taskTime) throws Exception {
        IndustrialReportTaskCenter center = new IndustrialReportTaskCenter();
        center.setTaskUrl(reportUrl);
        center.setTaskId(task.getId());
        center.setReportTemplate(task.getReportTemplate());
        center.setReportObj(task.getReportObj());
        center.setReportCycle(task.getReportCycle());
        center.setGenDate(now);
        center.setSendDate(taskTime);
        center.setDeadline(calcDeadline(taskTime, task.getValidityPeriod()));
        center.setTaskStatus(0L);
        center.setSendNum(0L);
        center.setRemark(task.getRemark());
        Date reportCollectDate = calcReportCollectDate(task);
        // 新增：采集周期日期
        center.setReportCollectDate(calcReportCollectDate(task));
        String cycleName = buildReportCycleDate(task.getReportCycle(), reportCollectDate);
        center.setTaskName(cycleName + task.getTaskName());
        return center;
    }

    // -------------------------------------------------------------------
    // 计算数据采集周期日期（reportCollectDate）
    // -------------------------------------------------------------------
    private Date calcReportCollectDate(IndustrialReportTask task) {
        String cycle = task.getReportCycle();
        String type = task.getReportCollectType() == null ? "1" : task.getReportCollectType();

        Calendar cal = Calendar.getInstance();

        if ("2".equals(cycle)) { // 月度
            if ("2".equals(type)) {
                cal.add(Calendar.MONTH, -1);
            }
            cal.set(Calendar.DAY_OF_MONTH, 1);

        } else if ("3".equals(cycle)) { // 年度
            if ("2".equals(type)) {
                cal.add(Calendar.YEAR, -1);
            }
            cal.set(Calendar.MONTH, Calendar.JANUARY);
            cal.set(Calendar.DAY_OF_MONTH, 1);
        }

        return cal.getTime();
    }

    // -------------------------------------------------------------------
    // 计算有效期 deadline
    // -------------------------------------------------------------------
    private Date calcDeadline(Date taskTime, Long validityPeriod) {
        int days = validityPeriod == null ? 0 : validityPeriod.intValue();
        Calendar cal = Calendar.getInstance();
        cal.setTime(taskTime);
        cal.add(Calendar.DAY_OF_MONTH, days);
        return cal.getTime();
    }

    // -------------------------------------------------------------------
    // 构建时间（日期 + 指定 HH:mm:ss）
    // -------------------------------------------------------------------
    private Date buildDateWithTime(Date baseDate, String timeStr) throws Exception {
        if (timeStr == null || timeStr.isEmpty()) {
            return baseDate;
        }
        String full = dateFormat.format(baseDate) + " " + timeStr;
        return dateTimeFormat.parse(full);
    }

    /**
     * 与前端保持一致的周期名称生成
     *
     * @param cycle       报告周期 1一次性 2月度 3年度
     * @param collectDate 采集周期日期
     */
    private String buildReportCycleDate(String cycle, Date collectDate) {
        if (cycle == null || collectDate == null) {
            return "";
        }

        Calendar cal = Calendar.getInstance();
        cal.setTime(collectDate);

        // 一次性
        if ("1".equals(cycle)) {
            return "";
        }

        // 月度：yyyy年MM月度
        if ("2".equals(cycle)) {
            int year = cal.get(Calendar.YEAR);
            int month = cal.get(Calendar.MONTH) + 1;
            return String.format("%d年%02d月度", year, month);
        }

        // 年度：yyyy年度
        if ("3".equals(cycle)) {
            int year = cal.get(Calendar.YEAR);
            return String.format("%d年度", year);
        }

        return "";
    }

}
